home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-04 | 29.0 KB | 903 lines | [TEXT/KAHL] |
- /***************************************************** IMPLEMENTATION
- DATE: 10/28/93
- AUTHOR: Eric R. Rosé
-
- CLASS: CPPPackedTreeNode
-
- SUPERCLASS: CPPTreeNode
-
- This C++ class manages the visual representation of a node
- in a hierarchical tree
-
- ********************************************************************/
-
- #include <CPPPackedTreeNode.h>
- #include <CPPVisualTree.h>
- #include "CPPString.h"
- #include <MathTools.h>
- #include <ToolboxTools.h>
- #include <math.h>
-
-
- #define hMargin 2
- #define vMargin 2
-
- short *Contour = NULL;
-
- extern void SetNotYetPlaced (CPPTreeNode *theNode, long param);
-
- /*-----------------------------------------------------------------*/
- /*------------------------ PUBLIC METHODS -------------------------*/
- /*-----------------------------------------------------------------*/
-
- CPPPackedTreeNode::CPPPackedTreeNode (CPPObject *NodeData,
- CPPTree *BelongsTo,
- Boolean becomeOwner,
- Boolean selected) :
- CPPVisualTreeNode (NodeData, BelongsTo, becomeOwner, selected)
- {
- SetPt (&this->nodeSize, 0, 0);
- this->familySize = this->childSize = this->nodeSize;
-
- SetRect (&this->nodeRect, 0, 0, 0, 0);
- this->familyRect = this->childRect = this->nodeRect;
-
- SetPt (&this->estTopLeft, 0, 0);
-
- this->needsDraw = TRUE;
- this->needsResize = TRUE;
- this->isSelected = selected;
- }
-
- /*-----------------------------------------------------------------*/
-
- CPPPackedTreeNode::~CPPPackedTreeNode (void)
- {
-
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPPackedTreeNode::Member (char *className)
- {
- if (strcmp(className, CPPPackedTreeNode::ClassName()) == 0)
- return TRUE;
- else
- return CPPVisualTreeNode::Member(className);
- }
-
- /*-----------------------------------------------------------------*/
-
- char *CPPPackedTreeNode::ClassName (void)
- {
- return "CPPPackedTreeNode";
- }
-
- /*-----------------------------------------------------------------*/
-
- CPPObject *CPPPackedTreeNode::Clone(void)
- {
- return NULL;
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::EraseNode (Boolean wholeFamily)
- {
- PenState OldState;
-
- // prepare the grafport to draw tree nodes
- if (this->Root)
- ((CPPVisualTree *)this->Root)->Prepare(this);
-
- EraseRect (&this->nodeRect);
- EraseJoin((CPPVisualTreeNode *)this->Parent, this);
-
- if (wholeFamily)
- {
- for (long i = 1; i <= numItems; i++)
- ((CPPPackedTreeNode *)NthChild (i))->EraseNode(wholeFamily);
- }
-
- // restore the original grafport state
- ((CPPVisualTree *)this->Root)->Restore(this);
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::DoCalcFamilySize(void)
- /* Calculate how large the node's children, and the entire node */
- /* are, storing the values in childSize and familySize */
- {
- CPPPackedTreeNode *theChild;
- orientStyle Orient = GetOrientation();
- short betweenNodeMargin = GetNodeMargin();
-
- if (!this->needsResize) return;
- this->needsResize = FALSE;
- this->CalcNodeSize(); // figure out node's size first
-
-
- SetPt (&this->childSize, 0, 0); // assume we have no children
-
- // iterate over all the children of this node, accumulating
- // their height and width
- for (long i = 1; i<= this->numItems; i++)
- {
- theChild = (CPPPackedTreeNode *)NthChild(i);
- theChild->DoCalcFamilySize();
- if ((Orient == kTopDown) || (Orient == kBottomUp))
- {
- childSize.h += theChild->nodeSize.h + ((i != this->numItems) ? betweenNodeMargin : 0);
- childSize.v = Max (theChild->nodeSize.v, childSize.v);
- }
- else
- {
- childSize.v += theChild->nodeSize.v + ((i != this->numItems) ? betweenNodeMargin : 0);
- childSize.h = Max (theChild->nodeSize.h, childSize.h);
- }
- }
-
- // Set the size of the family - a combination of the node size,
- // child size, and branch length;
- if ((Orient == kTopDown) || (Orient == kBottomUp))
- {
- familySize.h = Max(childSize.h, nodeSize.h);
- familySize.v = nodeSize.v;
- if (childSize.v > 0)
- familySize.v += childSize.v + GetBranchLength();
- }
- else
- {
- familySize.v = Max(childSize.v, nodeSize.v);
- familySize.h = nodeSize.h;
- if (childSize.h > 0)
- familySize.h += childSize.h + GetBranchLength();
- }
-
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::CPBTopTraverse (short level, short levelOffset)
- /* the recursive traversal part of the CalcFamilyBounds for */
- /* vertically oriented trees */
- {
- CPPPackedTreeNode *theChild;
- short childWidth = this->childSize.h;
- long i;
- justStyle Just = GetJustification();
- orientStyle Orient = GetOrientation();
- Rect emptyRect = {0,0,0,0};
- Boolean eraseKidJoins = FALSE;
- Rect OldNodeRect = this->nodeRect,
- OldGChildRect = this->gChildRect;
- Rect newNodeRect = {0,0,0,0},
- newFamilyRect = {0,0,0,0},
- newChildRect = {0,0,0,0},
- newGChildRect = {0,0,0,0};
-
- // make sure the node's estimate is below the lowest node
- // on this level
- this->estTopLeft.h = Max (this->estTopLeft.h, Contour[level]);
-
- // if the node has children, iterate over them, giving each an estimated
- // position and then calling this routine recursively
- if (this->numItems)
- {
- for (i = 1; i <= this->numItems; i++)
- {
- theChild = (CPPPackedTreeNode *)NthChild(i);
- if (theChild)
- {
- if (i == 1)
- {
- // estimate the top left corner of the first child node
- switch (Just) {
- case kJustCenter:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h + (this->nodeSize.h / 2) - (childWidth / 2),
- this->estTopLeft.v + levelOffset);
- break;
-
- case kJustLeft:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h, this->estTopLeft.v + levelOffset);
- break;
-
- case kJustRight:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h + this->nodeSize.h - childWidth,
- this->estTopLeft.v + levelOffset);
- break;
- }
-
- // place its children
- theChild->CPBTopTraverse(level+1, Max (this->childSize.v+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- newGChildRect = theChild->nodeRect;
- // accumulate the child into the rect enclosing all children
- newChildRect = theChild->familyRect;
- }
- else
- {
- SetPt(&theChild->estTopLeft,
- Contour[level+1],
- this->estTopLeft.v + levelOffset);
-
- // place its children
- theChild->CPBTopTraverse(level+1, Max (this->childSize.v+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- UnionRect (&newGChildRect, &theChild->nodeRect, &newGChildRect);
- // accumulate the child into the rect enclosing all children
- UnionRect (&newChildRect, &theChild->familyRect, &newChildRect);
- }
- }
- }
- }
-
- // set the node's rectangle
- SetRect (&newNodeRect, this->estTopLeft.h, this->estTopLeft.v,
- this->estTopLeft.h + this->nodeSize.h,
- this->estTopLeft.v + this->nodeSize.v);
-
- // justify the node with respect to its children
- if (this->numItems)
- {
- switch (Just) {
- case kJustCenter:
- CenterRect (&newNodeRect, &newGChildRect, TRUE, FALSE);
- break;
- case kJustRight:
- AlignRect (&newNodeRect, &newGChildRect, kRight, kNone);
- break;
- case kJustLeft:
- AlignRect (&newNodeRect, &newGChildRect, kLeft, kNone);
- break;
- }
-
- // build the rectangle which encloses the node and its children
- UnionRect (&newNodeRect, &newChildRect, &newFamilyRect);
- }
- else
- newFamilyRect = newNodeRect;
-
- // this routine is the same for both the packed and visual tree nodes
-
- // if the node has changed position or size, erase it and
- // note that it must be redrawn
- if (!EqualRect (&OldNodeRect, &newNodeRect))
- {
- if (!EqualRect (&emptyRect, &OldNodeRect))
- EraseNode (FALSE);
- this->needsDraw = eraseKidJoins = TRUE;
- }
- else // if the node's children have moved, redraw it too
- if (Just != kJustCenter)
- {
- if ((Orient == kBottomUp) || (Orient == kTopDown))
- {
- if (OldGChildRect.right - OldGChildRect.left !=
- newGChildRect.right - newGChildRect.left)
- this->needsDraw = eraseKidJoins = TRUE;
- }
- else
- {
- if (OldGChildRect.bottom - OldGChildRect.top !=
- newGChildRect.bottom - newGChildRect.top)
- this->needsDraw = eraseKidJoins = TRUE;
- }
- }
-
- if (eraseKidJoins)
- for (i = 1; i <= this->numItems; i++)
- EraseJoin (this, (CPPVisualTreeNode *)NthChild(i));
-
- this->nodeRect = newNodeRect;
- this->childRect = newChildRect;
- this->familyRect = newFamilyRect;
- this->gChildRect = newGChildRect;
-
- this->notYetPlaced = FALSE;
-
- // update the value of the lowest point in the current level
- Contour[level] = newNodeRect.right + GetNodeMargin();
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::CPBBottomTraverse (short level, short levelOffset)
- /* the recursive traversal part of the CalcFamilyBounds for */
- /* Bottom-Up oriented trees */
- {
- CPPPackedTreeNode *theChild;
- short childWidth = this->childSize.h;
- long i;
- justStyle Just = GetJustification();
-
- orientStyle Orient = GetOrientation();
- Rect emptyRect = {0,0,0,0};
- Boolean eraseKidJoins = FALSE;
- Rect OldNodeRect = this->nodeRect,
- OldGChildRect = this->gChildRect;
- Rect newNodeRect = {0,0,0,0},
- newFamilyRect = {0,0,0,0},
- newChildRect = {0,0,0,0},
- newGChildRect = {0,0,0,0};
-
- // make sure the node's estimate is below the lowest node
- // on this level
- this->estTopLeft.h = Max (this->estTopLeft.h, Contour[level]);
-
- // if the node has children, iterate over them, giving each an estimated
- // position and then calling this routine recursively
- if (this->numItems)
- {
- for (i = 1; i <= this->numItems; i++)
- {
- theChild = (CPPPackedTreeNode *)NthChild(i);
- if (theChild)
- {
- if (i == 1)
- {
- // estimate the top left corner of the first child node
- switch (Just) {
- case kJustCenter:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h + (this->nodeSize.h / 2) - (childWidth / 2),
- this->estTopLeft.v - levelOffset);
- break;
-
- case kJustLeft:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h, this->estTopLeft.v - levelOffset);
- break;
-
- case kJustRight:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h + this->nodeSize.h - childWidth,
- this->estTopLeft.v - levelOffset);
- break;
- }
-
- // place its children
- theChild->CPBBottomTraverse(level+1, Max (this->childSize.v+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- newGChildRect = theChild->nodeRect;
- // accumulate the child into the rect enclosing all children
- newChildRect = theChild->familyRect;
- }
- else
- {
- SetPt(&theChild->estTopLeft,
- Contour[level+1],
- this->estTopLeft.v - levelOffset);
-
- // place its children
- theChild->CPBBottomTraverse(level+1, Max (this->childSize.v+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- UnionRect (&newGChildRect, &theChild->nodeRect, &newGChildRect);
- // accumulate the child into the rect enclosing all children
- UnionRect (&newChildRect, &theChild->familyRect, &newChildRect);
- }
- }
- }
- }
-
- // set the node's rectangle
- SetRect (&newNodeRect, this->estTopLeft.h,
- this->estTopLeft.v - this->nodeSize.v,
- this->estTopLeft.h + this->nodeSize.h,
- this->estTopLeft.v);
-
- // center this node over all of its children
- if (this->numItems)
- {
- // justify the node with respect to its children
- switch (Just) {
- case kJustCenter:
- CenterRect (&newNodeRect, &newGChildRect, TRUE, FALSE);
- break;
- case kJustRight:
- AlignRect (&newNodeRect, &newGChildRect, kRight, kNone);
- break;
- case kJustLeft:
- AlignRect (&newNodeRect, &newGChildRect, kLeft, kNone);
- break;
- }
-
- // build the rectangle which encloses the node and its children
- UnionRect (&newNodeRect, &newChildRect, &newFamilyRect);
- }
- else
- newFamilyRect = newNodeRect;
-
- #include <TreeNodeConds.cp>
-
- this->nodeRect = newNodeRect;
- this->childRect = newChildRect;
- this->familyRect = newFamilyRect;
- this->gChildRect = newGChildRect;
-
- this->notYetPlaced = FALSE;
-
- // update the value of the lowest point in the current level
- Contour[level] = newNodeRect.right + GetNodeMargin();
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::CPBRightTraverse (short level, short levelOffset)
- /* the recursive traversal part of the CalcFamilyBounds for */
- /* Right-to-left oriented trees */
- {
- CPPPackedTreeNode *theChild;
- short childHeight = this->childSize.v;
- long i;
- justStyle Just = GetJustification();
-
- orientStyle Orient = GetOrientation();
- Rect emptyRect = {0,0,0,0};
- Boolean eraseKidJoins = FALSE;
- Rect OldNodeRect = this->nodeRect,
- OldGChildRect = this->gChildRect;
- Rect newNodeRect = {0,0,0,0},
- newFamilyRect = {0,0,0,0},
- newChildRect = {0,0,0,0},
- newGChildRect = {0,0,0,0};
-
- // make sure the node's estimate is below the lowest node
- // on this level
- this->estTopLeft.v = Max (this->estTopLeft.v, Contour[level]);
-
- // if the node has children, iterate over them, giving each an estimated
- // position and then calling this routine recursively
- if (this->numItems)
- {
- for (i = 1; i <= this->numItems; i++)
- {
- theChild = (CPPPackedTreeNode *)NthChild(i);
- if (theChild)
- {
- if (i == 1)
- {
- // estimate the top left corner of the first child node
- switch (Just) {
- case kJustCenter:
- SetPt(&theChild->estTopLeft,
- this->estTopLeft.h - levelOffset,
- this->estTopLeft.v + (this->nodeSize.v / 2) - (childHeight / 2));
- break;
-
- case kJustTop:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h - levelOffset, this->estTopLeft.v);
- break;
-
- case kJustBottom:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h - levelOffset,
- this->estTopLeft.v + nodeSize.v - childHeight);
- break;
- }
-
- // place its children
- theChild->CPBRightTraverse(level+1, Max (this->childSize.h+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- newGChildRect = theChild->nodeRect;
- // accumulate the child into the rect enclosing all children
- newChildRect = theChild->familyRect;
- }
- else
- {
- SetPt(&theChild->estTopLeft,
- this->estTopLeft.h - levelOffset,
- Contour[level+1]);
-
- // place its children
- theChild->CPBRightTraverse(level+1, Max (this->childSize.h+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- UnionRect (&newGChildRect, &theChild->nodeRect, &newGChildRect);
- // accumulate the child into the rect enclosing all children
- UnionRect (&newChildRect, &theChild->familyRect, &newChildRect);
- }
- }
- }
- }
-
- // set the node's rectangle
- SetRect (&newNodeRect, this->estTopLeft.h - this->nodeSize.h,
- this->estTopLeft.v,
- this->estTopLeft.h,
- this->estTopLeft.v + this->nodeSize.v);
-
- // justify the node with respect to its children
- if (this->numItems)
- {
- switch (Just) {
- case kJustCenter:
- CenterRect (&newNodeRect, &newGChildRect, FALSE, TRUE);
- break;
- case kJustTop:
- AlignRect (&newNodeRect, &newGChildRect, kNone, kTop);
- break;
- case kJustBottom:
- AlignRect (&newNodeRect, &newGChildRect, kNone, kBottom);
- break;
- }
- // build the rectangle which encloses the node and its children
- UnionRect (&newNodeRect, &newChildRect, &newFamilyRect);
- }
- else
- newFamilyRect = newNodeRect;
-
- #include <TreeNodeConds.cp>
-
- this->nodeRect = newNodeRect;
- this->childRect = newChildRect;
- this->familyRect = newFamilyRect;
- this->gChildRect = newGChildRect;
-
- this->notYetPlaced = FALSE;
-
- // update the value of the lowest point in the current level
- Contour[level] = newNodeRect.bottom + GetNodeMargin();
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::CPBLeftTraverse (short level, short levelOffset)
- /* the recursive traversal part of the CalcFamilyBounds for */
- /* Left-to-right oriented trees */
- {
- CPPPackedTreeNode *theChild;
- short childHeight = this->childSize.v;
- long i;
- justStyle Just = GetJustification();
-
- orientStyle Orient = GetOrientation();
- Rect emptyRect = {0,0,0,0};
- Boolean eraseKidJoins = FALSE;
- Rect OldNodeRect = this->nodeRect,
- OldGChildRect = this->gChildRect;
- Rect newNodeRect = {0,0,0,0},
- newFamilyRect = {0,0,0,0},
- newChildRect = {0,0,0,0},
- newGChildRect = {0,0,0,0};
-
- // make sure the node's estimate is below the lowest node
- // on this level
- this->estTopLeft.v = Max (this->estTopLeft.v, Contour[level]);
-
- // if the node has children, iterate over them, giving each an estimated
- // position and then calling this routine recursively
- if (this->numItems)
- {
- for (i = 1; i <= this->numItems; i++)
- {
- theChild = (CPPPackedTreeNode *)NthChild(i);
- if (theChild)
- {
- if (i == 1)
- {
- // estimate the top left corner of the first child node
- switch (Just) {
- case kJustCenter:
- SetPt(&theChild->estTopLeft,
- this->estTopLeft.h + levelOffset,
- this->estTopLeft.v + (this->nodeSize.v / 2) - (childHeight / 2));
- break;
-
- case kJustTop:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h + levelOffset, this->estTopLeft.v);
- break;
-
- case kJustBottom:
- SetPt (&theChild->estTopLeft,
- this->estTopLeft.h + levelOffset,
- this->estTopLeft.v + nodeSize.v - childHeight);
- break;
- }
-
- // place its children
- theChild->CPBLeftTraverse(level+1, Max (this->childSize.h+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- newGChildRect = theChild->nodeRect;
- // accumulate the child into the rect enclosing all children
- newChildRect = theChild->familyRect;
- }
- else
- {
- SetPt(&theChild->estTopLeft,
- this->estTopLeft.h + levelOffset,
- Contour[level+1]);
-
- // place its children
- theChild->CPBLeftTraverse(level+1, Max (this->childSize.h+5, GetBranchLength()));
- // accumulate it into the rect we will use to center ourselves
- UnionRect (&newGChildRect, &theChild->nodeRect, &newGChildRect);
- // accumulate the child into the rect enclosing all children
- UnionRect (&newChildRect, &theChild->familyRect, &newChildRect);
- }
- }
- }
- }
-
- // set the node's rectangle
- SetRect (&newNodeRect, this->estTopLeft.h, this->estTopLeft.v,
- this->estTopLeft.h + this->nodeSize.h,
- this->estTopLeft.v + this->nodeSize.v);
-
- // center this node over all of its children
- if (this->numItems)
- {
- switch (Just) {
- case kJustCenter:
- CenterRect (&newNodeRect, &newGChildRect, FALSE, TRUE);
- break;
- case kJustTop:
- AlignRect (&newNodeRect, &newGChildRect, kNone, kTop);
- break;
- case kJustBottom:
- AlignRect (&newNodeRect, &newGChildRect, kNone, kBottom);
- break;
- }
- // build the rectangle which encloses the node and its children
- UnionRect (&newNodeRect, &newChildRect, &newFamilyRect);
- }
- else
- newFamilyRect = newNodeRect;
-
- #include <TreeNodeConds.cp>
-
- this->nodeRect = newNodeRect;
- this->childRect = newChildRect;
- this->familyRect = newFamilyRect;
- this->gChildRect = newGChildRect;
-
- this->notYetPlaced = FALSE;
-
- // update the value of the lowest point in the current level
- Contour[level] = newNodeRect.bottom + GetNodeMargin();
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::PostProcess (Boolean isVertical)
- /* go back through the tree and make sure that all nodes which */
- /* do not have children are centered between their siblings */
- {
- CPPPackedTreeNode *tempNode, *leftNode, *rightNode;
- Rect tempRect, newnodeRect;
- long rightMost, leftMost;
- short outerSpan, innerSpan, margin, side;
- Point newTopLeft;
-
- // the for loop guarantees that all nodes will be visited
- for (long i = 1; i <= numItems; i++)
- {
- tempNode = (CPPPackedTreeNode *)NthChild (i);
- if (tempNode && tempNode->numItems)
- tempNode->PostProcess (isVertical);
- }
-
- // this section looks at all the children of the visited node
- // and distributes childless nodes between their populated neighbors
- if (this->numItems)
- {
- leftMost = 1;
- while (leftMost < this->numItems)
- {
- // advance leftMost to point to the leftmost populated node
- while ((leftMost <= numItems) &&
- ((leftNode = (CPPPackedTreeNode *)NthChild(leftMost))->numItems == 0))
- leftMost++;
-
- rightMost = leftMost;
-
- if (leftMost >= numItems-1) return;
-
- innerSpan = 0;
- // advance rightMost to point to the next populated node
- rightMost = leftMost+1;
- while ((rightMost <= numItems) &&
- ((rightNode = (CPPPackedTreeNode *)NthChild(rightMost))->numItems == 0))
- {
- innerSpan += (isVertical) ? rightNode->nodeSize.h : rightNode->nodeSize.v;
- rightMost++;
- }
-
- if ((rightMost <= numItems) && (rightMost - leftMost > 1))
- {
- // at this point we have at least one childless node between
- // leftMost and rightMost. Distribute it/them within the
- // boundaries of the left & right nodes by calculating what the
- // size of the margin between the childless nodes should be
- if (isVertical)
- {
- outerSpan = rightNode->nodeRect.left - leftNode->nodeRect.right;
- margin = Max (hMargin, (outerSpan - innerSpan) / (rightMost - leftMost));
- side = leftNode->nodeRect.right;
- for (long j = leftMost+1; j < rightMost; j++)
- {
- tempNode = (CPPPackedTreeNode *)NthChild (j);
- if (tempNode)
- {
- newTopLeft = topLeft(tempNode->nodeRect);
- newTopLeft.h = side + margin;
- tempNode->ShiftNode(newTopLeft);
- side = tempNode->nodeRect.right;
- }
- }
- }
- else
- {
- outerSpan = rightNode->nodeRect.top - (leftNode->nodeRect.bottom + 1);
- margin = Min (hMargin, (outerSpan - innerSpan) / (rightMost - leftMost));
- side = leftNode->nodeRect.bottom;
- for (long k = leftMost+1; k < rightMost; k++)
- {
- tempNode = (CPPPackedTreeNode *)NthChild (k);
- if (tempNode)
- {
- newTopLeft = topLeft(tempNode->nodeRect);
- newTopLeft.v = side + margin;
- tempNode->ShiftNode(newTopLeft);
- side = tempNode->nodeRect.bottom;
- } // if tempnode
- } // for k
- } // else
- } // if rightmost <= numitems...
-
- leftMost = rightMost + 1;
-
- } // while
- } // if this->numitems
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::DoCalcFamilyBounds (Point TopLeftCorner)
- /* this routine uses the tree drawing algorithm from SAGE */
- /* (Steve Roth @ Carnegie Mellon University) to position the */
- /* nodes in the family */
- {
- orientStyle Orient = GetOrientation();
-
- // allocate the array to keep track of where nodes can be placed
- Contour = (short *)NewPtrClear(sizeof(short) * (FamilyDepth(0) + 1));
-
- this->estTopLeft = TopLeftCorner;
-
- switch (Orient) {
- case kTopDown :
- this->CPBTopTraverse (1, Max(GetBranchLength(), this->nodeSize.v + 5));
- break;
- case kBottomUp :
- this->CPBBottomTraverse(1, Max(GetBranchLength(), this->nodeSize.v + 5));
- break;
- case kRight2Left :
- this->CPBRightTraverse(1, Max(GetBranchLength(), this->nodeSize.h + 5));
- break;
- case kLeft2Right :
- this->CPBLeftTraverse(1, Max(GetBranchLength(), this->nodeSize.h + 5));
- break;
- }
-
- // add a step which goes back and distributes childless nodes
- if (GetJustification() == kJustCenter)
- PostProcess(((Orient == kTopDown) | (Orient == kBottomUp)) ? TRUE : FALSE);
-
- DisposePtr((Ptr)Contour);
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::ReceiveMessage (CPPGossipMonger *toldBy,
- short reason, void* info)
- {
- CPPPackedTreeNode *topNode = (this->Root) ? (CPPPackedTreeNode *)this->Root->GetTopMostNode() : NULL;
- Boolean childChanged, familyChanged;
- RgnHandle Rgn1, Rgn2;
- static short timesCalled = 0; // tracks recursion
- Rect oldFamilyRect;
- Point OldFamilySize;
-
- if (topNode)
- {
- oldFamilyRect = topNode->familyRect;
- OldFamilySize = topNode->familySize;
- }
- else
- {
- SetRect (&oldFamilyRect, 0, 0, 0, 0);
- SetPt (&OldFamilySize, 0, 0);
- }
-
- switch (reason) {
- case kEraseFamily :
- EraseNode ((Boolean)info);
- break;
-
- case kDrawFamily :
- DrawNode ((Boolean)info, TRUE);
- break;
-
- case kResizeFamily :
- ResizeFamily (TRUE);
- if (this->Root)
- ((CPPVisualTree *)this->Root)->AdjustTree();
- break;
-
- case kMoveFamily :
- MoveFamily ((Point *)info);
- if (this->Root)
- ((CPPVisualTree *)this->Root)->AdjustTree();
- break;
-
- case kPrepareRemove :
- case kPrepareDelete :
- ((CPPPackedTreeNode *)info)->EraseNode(TRUE);
- ApplyToFamily((CPPPackedTreeNode *)info, SetNotYetPlaced, TRUE);
- break;
-
- case kNodeAdded : // the parent of the added node receives this message first
- case kNodeChangedData :
- case kChildDeleted :
- case kChildRemoved :
- if (this->Root)
- {
- ((CPPVisualTree *)this->Root)->Prepare((CPPObject *)1313L);
- ((CPPVisualTree *)this->Root)->ForceResize (FALSE);
-
- // erase & redraw ourselves so that the deleted node and its
- // joins are erased
- topNode->DrawNode(TRUE, FALSE);
- ((CPPVisualTree *)this->Root)->DrawAllJoins(TRUE);
- if ((OldFamilySize.h > topNode->familySize.h) || (OldFamilySize.v > topNode->familySize.v))
- {
- Rgn1 = NewRgn();
- Rgn2 = NewRgn();
- RectRgn(Rgn1, &oldFamilyRect);
- RectRgn(Rgn2, &topNode->familyRect);
- XorRgn (Rgn1, Rgn2, Rgn1);
- EraseRgn (Rgn1);
- DisposeRgn(Rgn1);
- DisposeRgn(Rgn2);
- }
- ((CPPVisualTree *)this->Root)->AdjustTree();
-
- ((CPPVisualTree *)this->Root)->Restore((CPPObject *)1313L);
- }
- break;
-
- default:
- CPPTreeNode::ReceiveMessage (toldBy, reason, info);
- break;
- }
- }
-
- /*-----------------------------------------------------------------*/
- /*---------------------- PRIVATE METHODS --------------------------*/
- /*-----------------------------------------------------------------*/
-
- void CPPPackedTreeNode::ShiftNode (Point newTopLeft)
- /* Called by PostProcess to move a childless node over to the */
- /* specified position after erasing it and the join to its parent */
- {
- if (!EqualPt(topLeft(this->nodeRect), newTopLeft))
- {
- // erase the node & note that it must be redrawn
- EraseJoin ((CPPPackedTreeNode *)this->Parent, this);
- EraseNode (TRUE);
- this->needsDraw = TRUE;
-
- // move the node and family rects
- OffsetRect (&this->nodeRect, newTopLeft.h - this->nodeRect.left,
- newTopLeft.v - this->nodeRect.top);
- this->familyRect = this->nodeRect;
- }
- }
-
-